#!/usr/bin/env python
##################################################
# Gnuradio Python Flow Graph
# Title: QPSK
# Author: Chris Evans, Garrett Vanhoy
# Description: QPSK
# Generated: Tue Aug  2 17:14:19 2011
##################################################

from gnuradio import eng_notation
from gnuradio import gr
from gnuradio.eng_option import eng_option
from gnuradio.gr import firdes
from grc_gnuradio import blks2 as grc_blks2
from optparse import OptionParser
import random

class QPSK(gr.top_block):

	def __init__(self, txamp=1, noiseamp=.1):
		gr.top_block.__init__(self, "QPSK")

		##################################################
		# Parameters
		##################################################
		self.txamp = txamp
		self.noiseamp = noiseamp

		##################################################
		# Variables
		##################################################
		self.const = const = complex(1, 1)/1.414, complex(-1, 1)/1.414, complex(-1, -1)/1.414, complex(1, -1)/1.414
		self.values1 = values1 = tuple(range(len(const)))
		self.samp_rate = samp_rate = 32000
		self.bit_per_chunk = bit_per_chunk = 2
		string = "self.decode_const = "
		for x in self.const:
			str2 = str(float(self.txamp)*x)
			if len(str2) is not 0:
				if str2[len(str2) - 1] == ")":
					string += str2[1: len(str2) - 1] + ", "
				else:
					string += str2 + ", "
		string = string[0:len(string) - 2]
		exec string
		self.vector = []
		for x in range(512):
			self.vector.append(random.randint(0, 255))
		##################################################
		# Blocks
		##################################################
		self.blks2_error_rate = grc_blks2.error_rate(
			type='BER',
			win_size=1000,
			bits_per_symbol=2,
		)
		self.gr_add_xx_0 = gr.add_vcc(1)
		self.gr_chunks_to_symbols_xx = gr.chunks_to_symbols_bc((const), 1)
		self.gr_constellation_decoder_cb = gr.constellation_decoder_cb((self.decode_const), (values1))
		self.gr_multiply_const_vxx_0 = gr.multiply_const_vcc((txamp, ))
		self.gr_noise_source_x_0 = gr.noise_source_c(gr.GR_GAUSSIAN, noiseamp, 42)
		self.gr_packed_to_unpacked_xx_0 = gr.packed_to_unpacked_bb(bit_per_chunk, gr.GR_MSB_FIRST)
		self.gr_throttle_0 = gr.throttle(gr.sizeof_gr_complex*1, samp_rate)
		self.gr_unpacked_to_packed_xx_0 = gr.unpacked_to_packed_bb(bit_per_chunk, gr.GR_MSB_FIRST)
		self.gr_vector_sink_x_0 = gr.vector_sink_f(1)
		self.gr_vector_source_x_0 = gr.vector_source_b(self.vector, False, 1)

		##################################################
		# Connections
		##################################################
		self.connect((self.gr_add_xx_0, 0), (self, 0))
		self.connect((self.gr_constellation_decoder_cb, 0), (self.gr_unpacked_to_packed_xx_0, 0))
		self.connect((self.gr_noise_source_x_0, 0), (self.gr_add_xx_0, 1))
		self.connect((self.gr_add_xx_0, 0), (self.gr_constellation_decoder_cb, 0))
		self.connect((self.gr_packed_to_unpacked_xx_0, 0), (self.gr_chunks_to_symbols_xx, 0))
		self.connect((self.gr_unpacked_to_packed_xx_0, 0), (self.blks2_error_rate, 1))
		self.connect((self.gr_throttle_0, 0), (self.gr_multiply_const_vxx_0, 0))
		self.connect((self.gr_multiply_const_vxx_0, 0), (self.gr_add_xx_0, 0))
		self.connect((self.gr_chunks_to_symbols_xx, 0), (self.gr_throttle_0, 0))
		self.connect((self.gr_vector_source_x_0, 0), (self.blks2_error_rate, 0))
		self.connect((self.gr_vector_source_x_0, 0), (self.gr_packed_to_unpacked_xx_0, 0))
		self.connect((self.blks2_error_rate, 0), (self.gr_vector_sink_x_0, 0))

	def get_txamp(self):
		return self.txamp

	def set_txamp(self, txamp):
		self.txamp = txamp
		self.gr_multiply_const_vxx_0.set_k((self.txamp, ))

	def get_noiseamp(self):
		return self.noiseamp

	def set_noiseamp(self, noiseamp):
		self.noiseamp = noiseamp
		self.gr_noise_source_x_0.set_amplitude(self.noiseamp)

	def get_const(self):
		return self.const

	def set_const(self, const):
		self.const = const
		self.set_values1(tuple(range(len(self.const))))

	def get_values1(self):
		return self.values1

	def set_values1(self, values1):
		self.values1 = values1

	def get_samp_rate(self):
		return self.samp_rate

	def set_samp_rate(self, samp_rate):
		self.samp_rate = samp_rate

	def get_bit_per_chunk(self):
		return self.bit_per_chunk

	def set_bit_per_chunk(self, bit_per_chunk):
		self.bit_per_chunk = bit_per_chunk

if __name__ == '__main__':
	parser = OptionParser(option_class=eng_option, usage="%prog: [options]")
	parser.add_option("", "--txamp", dest="txamp", type="eng_float", default=eng_notation.num_to_str(1),
		help="Set txamp [default=%default]")
	parser.add_option("", "--noiseamp", dest="noiseamp", type="eng_float", default=eng_notation.num_to_str(.1),
		help="Set noiseamp [default=%default]")
	(options, args) = parser.parse_args()
	tb = QPSK(txamp=options.txamp, noiseamp=options.noiseamp)
	tb.start()
